package org.ala.tiktools.mybatis.pager;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.ala.tiktools.mybatis.commons.MethodUtils;
import org.ala.tiktools.mybatis.expand.ExpandData;
import org.ala.tiktools.tools.CachingKVTools;
import org.apache.ibatis.session.SqlSession;
import org.springframework.util.Assert;

/**
 * 分页处理逻辑
 * - 么办法，Mybatis的拦截器无法做到改变返回值类型（默认调的是selectList）
 *
 * @author ala
 * @date 2025-01-08 10:17
 */
public class PagerHandler {


    /**
     *  Pager类型的参数在args中的下标
     */
    protected CachingKVTools<Method, Integer> pagerIndexMapper = new CachingKVTools<Method, Integer>(-1, MethodUtils::getPageIndex);
    /**
     *  每个Param在参数数组中的下标
     */
    protected CachingKVTools<Method, Map<String, Integer>> paramIndexMapper = new CachingKVTools<>(NULL_PARAM_INDEX, MethodUtils::getParamIndex);
    /**
     *  空值映射
     */
    protected static Map<String, Integer> NULL_PARAM_INDEX = new HashMap<>(0);

    int c = 0;
    /**
     *  执行分页逻辑
     */
    public Pager doPager(Pagement pagement, Method method, Object[] args, Map<String, ExpandData> expandDatas, SqlSession sqlSession) throws Exception {
        String selectId = String.format("%s.%s.%s", method.getDeclaringClass().getPackage().getName(),method.getDeclaringClass().getSimpleName(), method.getName());

        //  取pager参数
        Pager pager = getPager(method, args);
        Assert.notNull(pager, String.format("@Pagement注解的分页方法，必须含有Pager类型参数，且参数必须含@Param(\"page\") selectId:%s", selectId));

        long now = System.currentTimeMillis();

        //  查询本次记录
        Object pargs = convertParam(method, args, expandDatas);
        List list = sqlSession.selectList(selectId, pargs);
        pager.setDatas(list);

        long t1 = System.currentTimeMillis() - now;
        now = System.currentTimeMillis();

        //  查询总记录数
        if (pagement != null && pager.isQueryTotal()) {
            String countId = String.format("%s.%s.%s", method.getDeclaringClass().getPackage().getName(), method.getDeclaringClass().getSimpleName(), pagement.count());
            pager.setTotal(sqlSession.selectOne(countId, pargs));
            pager.setTotalPage(pager.getTotal() / pager.getSize() + (pager.getTotal() % pager.getSize() == 0 ? 0 : 1));
        }

        long t2 = System.currentTimeMillis() - now;
        now = System.currentTimeMillis();

//        System.out.printf("thread:%s t1:%d t2:%d\n", Thread.currentThread().getName(), t1, t2);

        return pager;
    }

    /**
     *  取分页注解参数
     */
    protected Pager getPager(Method method, Object[] args) throws Exception {
        Integer idx = pagerIndexMapper.get(method);
        if (idx == -1) {return null;}
        return ((Pager) args[idx]).copy();
//        Pager p = (Pager)args[idx];
//        Pager pager = Pager.build(p.getNo(), p.getSize());
//        return pager;
    }

    /**
     *  参数转换
     *  <p> 按照method的参数注解转换成map
     *  <p> 如果参数不含@Param，原样返回
     */
    protected Object convertParam(Method method, Object[] args, Map<String, ExpandData> expandDatas) throws Exception {
        Map<String, Integer> tpl = paramIndexMapper.get(method);
        if (NULL_PARAM_INDEX.equals(tpl)) {return args;}
        Map<String, Object> map = new HashMap<>();
        tpl.forEach((k,v) -> {
            map.put(k, args[v]);
        });
        if (expandDatas != null && !expandDatas.isEmpty()) {
            expandDatas.forEach((k,v) -> {
                if (v.isExpandToMBatis()) {
                    map.put(k, v.getValue());
                }
            });
        }
        return map;
    }
}
